/**
 * @Author Puzzle
 * @Date 2022/6/22 10:05 上午
 **/

package service

import (
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"zsc-boot/app/system_layer/model"
	"zsc-boot/app/system_layer/model/request"
	"zsc-boot/app/system_layer/model/response"
	"zsc-boot/core/orm"
)

var ServiceMenuService = new(serviceMenuService)

type serviceMenuService struct {
}

// CreateMenu 创建菜单
func (s *serviceMenuService) CreateMenu(menu model.ServiceMenu) (err error) {
	if !errors.Is(orm.GetDb().Where("rule_path = ?", menu.RulePath).First(&model.ServiceMenu{}).Error, gorm.ErrRecordNotFound) { // 判断用户名是否注册
		return errors.New("权限标识已存在!")
	}
	err = orm.GetDb().Create(&menu).Error
	return
}

// DeleteServiceMenu 删除菜单
func (s *serviceMenuService) DeleteServiceMenu(menu model.ServiceMenu) (err error) {
	var serviceMenu model.ServiceMenu
	err = orm.GetDb().Where("id = ?", menu.ID).First(&serviceMenu).Error

	return orm.GetDb().Transaction(func(tx *gorm.DB) error {
		// 删除菜单
		err = tx.Where("id = ?", serviceMenu.ID).Delete(&model.ServiceMenu{}).Error

		// 删除菜单角色关联
		return tx.Where("menu_code = ?", serviceMenu.RulePath).Delete(&model.ServiceRoleMenu{}).Error
	})
}

// UpdateServiceMenu 更新菜单
func (s *serviceMenuService) UpdateServiceMenu(menu model.ServiceMenu) (err error) {
	var oldMenu model.ServiceMenu
	if err = orm.GetDb().Where("id = ?", menu.ID).First(&oldMenu).Error; err != nil {
		return
	}
	if menu.RulePath != oldMenu.RulePath {
		if !errors.Is(orm.GetDb().Where("rule_path = ?", menu.RulePath).First(&model.ServiceMenu{}).Error, gorm.ErrRecordNotFound) {
			return errors.New("存在相同权限标识!")
		}
	}

	return orm.GetDb().Transaction(func(tx *gorm.DB) error {
		// 更新菜单
		err = tx.Updates(&menu).Error

		// 更新菜单标识
		return tx.Model(&model.ServiceRoleMenu{}).Where("menu_code = ?", oldMenu.RulePath).UpdateColumns(map[string]interface{}{
			"menu_code": menu.RulePath,
		}).Error
	})
}

// UpdateServiceMenuStatus 更新菜单状态
func (s *serviceMenuService) UpdateServiceMenuStatus(menu model.ServiceMenu) (err error) {
	err = orm.GetDb().Updates(&menu).Error
	return
}

// GetServiceMenu 获取菜单详情
func (s *serviceMenuService) GetServiceMenu(id uint) (err error, resp model.ServiceMenu) {
	err = orm.GetDb().Where("id = ?", id).Preload("Children.Children.Children").First(&resp).Error
	return
}

// GetServiceMenuList 获取菜单列表
func (s *serviceMenuService) GetServiceMenuList(info request.ServiceMenuSearch) (err error, list interface{}, total int64) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	var serviceMenus []model.ServiceMenu
	db := orm.GetDb().Model(&model.ServiceMenu{})
	if info.Name != "" {
		db.Where("name like ?", "%"+info.Name+"%")
	}
	if info.Visible != 0 {
		db.Where("visible = ?", info.Visible)
	}
	if info.Status != "" {
		db.Where("status = ?", info.Status)
	}
	if info.Belong != "" {
		db = db.Where("belong = ?", info.Belong)
	}
	if info.IsShortCut != 0 {
		db = db.Where("is_short_cut = ?", info.IsShortCut)
	} else {
		db = db.Where("parent_id = 0")
	}
	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Limit(limit).Offset(offset).Order("sequence desc").
		Preload("Children.Children.Children.Children").Find(&serviceMenus).Error
	return err, serviceMenus, total
}

func (s *serviceMenuService) MenuTransition(menus []model.ServiceMenu) []response.BaseMenuTree {
	menuList := make([]response.BaseMenuTree, 0)
	for _, v := range menus {
		menuList = append(menuList, response.BaseMenuTree{
			Name:     v.Name,
			RulePath: v.RulePath,
			Belong:   v.Belong,
			Children: s.MenuTransition(v.Children),
		})
	}
	return menuList
}
